package com.yesep.learn.design.creational.prototype;

/**
 * 原型模式（Prototype Pattern）是一种创建型设计模式，它允许通过复制已有的对象来创建新的对象，而无需在每次需要新对象时都显式地指定其具体的类。
 * 在原型模式中，新对象的创建是通过克隆一个已经存在的对象来完成的，这个已经存在的对象被称为“原型”。
 * <p>
 * 一、原型模式的定义
 * 原型模式定义了一个用于创建对象的接口，但让子类决定要实例化的类是哪一个。原型模式通过复制现有的实例来创建新的实例，这通常是通过实现一个特殊的 clone 方法来完成的。
 * 在Java中，这通常涉及到实现 Cloneable 接口并重写 Object 类的 clone() 方法。
 * <p>
 * 二、原型模式的优缺点
 * 优点：
 * <p>
 * 性能高：使用原型模式可以避免重复初始化对象，特别是在创建大量相似对象时，性能优势更加明显。
 * 简化创建过程：通过复制现有对象来创建新对象，可以简化对象的创建过程。
 * 灵活性和可扩展性：原型模式提供了动态的类实例化机制，可以在运行时根据需要动态地创建对象。
 * 解耦：客户端不需要知道对象的创建细节，只需要通过复制原型对象来创建新对象。
 * 缺点：
 * <p>
 * 实现复杂：需要实现 Cloneable 接口并重写 clone() 方法，如果对象包含复杂的引用类型，还需要考虑深拷贝和浅拷贝的问题。
 * 风险：在克隆对象时，如果处理不当，可能会引发一些难以察觉的错误，特别是在进行深拷贝时。
 * 依赖性：如果原型对象中包含对其他对象的引用，而这些对象又依赖于特定的状态或配置，那么克隆出来的对象可能会遇到状态不一致的问题。
 * 三、原型模式的实现步骤
 * 在Java中，实现原型模式通常需要以下步骤：
 * <p>
 * 实现Cloneable接口：原型类需要实现 Cloneable 接口，以表明该类支持克隆操作。
 * 重写clone方法：在原型类中重写 Object 类的 clone() 方法，以实现具体的克隆逻辑。通常，这涉及到调用 super.clone() 来获取对象的浅拷贝，并根据需要进行深拷贝。
 * 创建原型对象：通过构造函数或其他方式创建一个原型对象。
 * 复制原型对象：通过调用原型对象的 clone() 方法来创建新的对象。
 * 四、原型模式的应用场景
 * 原型模式适用于以下场景：
 * <p>
 * 对象的创建成本较高：如果创建对象的过程比较复杂或耗时较长，可以使用原型模式通过复制一个现有对象的属性和方法来创建新对象。
 * 需要创建大量相似的对象：如果需要创建大量相似的对象，可以先创建一个原型对象，然后通过复制原型对象来创建新对象。
 * 对象的修改频繁：如果对象的属性需要经常变化，而且每次变化都需要创建一个新的对象，可以使用原型模式通过复制原型对象来创建新对象并修改其属性。
 * 隐藏对象的创建细节：如果创建对象的细节比较复杂，不希望客户端直接与创建对象的过程耦合，可以使用原型模式让客户端通过复制一个已有对象来创建新对象而无需知道创建的细节。
 * 五、总结
 * 原型模式是一种强大的设计模式，它通过复制现有的对象来创建新对象，从而提高了对象的创建效率和性能。
 * 然而，在使用原型模式时需要注意实现的复杂性和风险，特别是在处理深拷贝和复杂引用类型时。
 * 同时，也需要根据具体的应用场景来选择是否使用原型模式。
 */
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        MyComputer computer = new MyComputer();
        computer.setModel("thinkpad");
        computer.setAudio("音响");
        computer.setKeyboard("键盘");
        computer.setMaster("主机");
        computer.setMouse("鼠标");
        computer.setScreen("显示器");
        System.out.println(computer.toString());
        MyComputer cloneComputer = computer.clone();
        cloneComputer.setModel("huawei");
        System.out.println(cloneComputer.toString());
    }
}
